/* 
* PROJECT: FLARManager
* http://transmote.com/flar
* Copyright 2009, Eric Socolofsky
* --------------------------------------------------------------------------------
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this framework; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
* 
* For further information please contact:
*	<eric(at)transmote.com>
*	http://transmote.com/flar
*/
package com.transmote.flar.camera {
	import com.transmote.flar.FLARManager;
	import com.transmote.flar.utils.geom.FLARGeomUtils;
	
	import flash.display.DisplayObjectContainer;
	import flash.geom.Matrix3D;
	import flash.geom.PerspectiveProjection;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	 * Provides values for setting up a DisplayObjectContainer
	 * for projection of 3D objects transformed by a tracker managed by FLARManager.
	 * <p>
	 * Borrows heavily from <a href="http://wonderfl.net/c/ztdH">code by Nutsu</a>
	 * </p>
	 *  
	 * @author	Eric Socolofsky
	 * @url		http://transmote.com/flar
	 */
	public class FLARCamera_Flash3D {
		private var _scene:DisplayObjectContainer;
		private var sceneScaleY:Number;
		private var sceneMatrix:Matrix3D;
		private var sceneProjection:PerspectiveProjection;
		
		/**
		 * Constructor.
		 * 
		 * @param	flarManager		A reference to the FLARManager instance used by this application.
		 * @param	viewportSize	A Rectangle that describes the viewport size for the application.
		 */
		public function FLARCamera_Flash3D (flarManager:FLARManager, viewportSize:Rectangle) {
			super();
			
			switch (flarManager.trackerId) {
				case FLARManager.TRACKER_ID_FLARTOOLKIT :
					this.init_FLARToolkit(flarManager, viewportSize);
					break;
				case FLARManager.TRACKER_ID_FLARE :
					this.init_flare(flarManager, viewportSize);
					break;
			}
		}
		
		public function get scene () :DisplayObjectContainer {
			return this._scene;
		}
		public function set scene (val:DisplayObjectContainer) :void {
			this._scene = val;
			this.sceneMatrix = new Matrix3D();
			this._scene.transform.matrix3D = this.sceneMatrix;
			this.scene.transform.perspectiveProjection = this.sceneProjection;
		}
		
		public function applyTransform (transformMatrix:Matrix3D) :void {
			this.sceneMatrix.rawData = Vector.<Number>([0,1,0,0, 1,0,0,0, 0,0,1,0, 0,0,0,1]);
			this.sceneMatrix.append(transformMatrix);
			this.sceneMatrix.appendScale(1, this.sceneScaleY, 1);
			this.sceneMatrix.appendTranslation(
				this._scene.transform.perspectiveProjection.projectionCenter.x,
				this._scene.transform.perspectiveProjection.projectionCenter.y,
				-this._scene.transform.perspectiveProjection.focalLength);
		}
		
		private function init_FLARToolkit (flarManager:FLARManager, viewportSize:Rectangle) :void {
			this.sceneProjection = new PerspectiveProjection();
			this.sceneProjection.projectionCenter = new Point(0.5*viewportSize.width, 0.5*viewportSize.height);
			
			var projectionMatrix:flash.geom.Matrix3D = flarManager.getProjectionMatrix(FLARManager.FRAMEWORK_ID_FLASH, viewportSize);
			var w:Number = projectionMatrix.rawData[0] / projectionMatrix.rawData[10];
			var h:Number = -projectionMatrix.rawData[5] / projectionMatrix.rawData[10];
			this.sceneScaleY = h / w;
			this.sceneProjection.focalLength = w / flarManager.flarCameraSource.trackerToDisplayRatio;
			
			this.sceneProjection.focalLength -= 150;	// dunno why subtracting 150 makes this work better, but it does...
		}
		
		private function init_flare (flarManager:FLARManager, viewportSize:Rectangle) :void {
			this.sceneProjection = new PerspectiveProjection();
			this.sceneProjection.projectionCenter = new Point(0.5*viewportSize.width, 0.5*viewportSize.height);
			
			// TEMP -- just copied from values generated by FLARToolkit
			// TODO: correctly calculate these values based on projection matrix generated by flare*
			this.sceneScaleY = 1.035;
			this.sceneProjection.focalLength = 427;
			
			/*
			var projectionMatrix:flash.geom.Matrix3D = flarManager.getProjectionMatrix(FLARManager.FRAMEWORK_ID_FLASH, viewportSize);
			
			trace("flare:\n"+FLARGeomUtils.dumpMatrix3D(projectionMatrix));
//			ftk:
//			350.4757		0.0000		158.2500		0.0000
//			0.0000		-363.0471		118.2500		0.0000
//			0.0000		0.0000		1.0000		0.0000
//			0.0000		0.0000		0.0000		1.0000

//			flare:
//			1.7353		0.0000		0.0000		0.0000
//			0.0000		2.2979		0.0000		0.0000
//			0.0015		0.0144		-1.0080		-1.0000
//			0.0000		0.0000		-40.1606		0.0000
			
			var w:Number = projectionMatrix.rawData[0] / projectionMatrix.rawData[10];
			var h:Number = -projectionMatrix.rawData[5] / projectionMatrix.rawData[10];
			this.sceneScaleY = h / w;
			this.sceneProjection.focalLength = w / flarManager.flarCameraSource.trackerToDisplayRatio;
			
			this.sceneProjection.focalLength -= 150;	// dunno why subtracting 150 makes this work better, but it does...
			*/
		}
	}
}